import atexit
import queue
import random
import os

import os
import time
import random
import threading
import atexit
from selenium import webdriver
from selenium.webdriver.chrome.service import Service
from selenium.webdriver.chrome.options import Options
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.by import By
from selenium.common.exceptions import TimeoutException, WebDriverException
from .logger import logger
from .config import config 
from .browser import browser_factory
from selenium import webdriver
from selenium.webdriver.chrome.service import Service
from selenium.webdriver.chrome.options import Options
from .logger import logger

from .config import config



headers_list = [
    {
        'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36',
        'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9',
        'Accept-Language': 'en-US,en;q=0.9'
    },
    {
        'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36',
        'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9',
        'Accept-Language': 'en-US,en;q=0.9'
    },
    {
        'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:89.0) Gecko/20100101 Firefox/89.0',
        'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9',
        'Accept-Language': 'en-US,en;q=0.9'
    }
]

class SingletonMeta(type):
    """单例元类，用于确保类只有一个实例。"""
    _instances = {}

    def __call__(cls, *args, **kwargs):
        if cls not in cls._instances:
            cls._instances[cls] = super().__call__(*args, **kwargs)
        return cls._instances[cls]


class BrowserFactory(metaclass=SingletonMeta):
    _instance = None
    max_instances = config.get_browser_config()['driver_count']
    _driver_queue = queue.Queue(maxsize=max_instances)
    def __new__(cls, *args, **kwargs):
        if not cls._instance:
            cls._instance = super().__new__(cls)
            cls._instance.__init__(*args, **kwargs)
        return cls._instance
    
    def init(self):
        for _ in range(self.max_instances):
            driver = self.create_driver()
            self._driver_queue.put(driver)
    """
    浏览器工厂类，用于创建 Chrome 浏览器驱动实例。
    """
    def get_driver(self):
        # 暂时保持不变，后续可能需要根据 tab 管理调整
        return self._driver_queue.get()

    def release_driver(self, driver):
        # 暂时保持不变，后续可能需要根据 tab 管理调整
        self._driver_queue.put(driver)

    @staticmethod
    def create_driver():
        """
        创建并返回一个配置好的 Chrome 浏览器驱动实例。

        :return: 配置好的 Chrome 浏览器驱动实例
        """
        # 定义 Chrome 驱动的路径
        chrome_driver_path = os.environ.get('CHROME_DRIVER_PATH')
        if not chrome_driver_path:
            raise ValueError('请设置 CHROME_DRIVER_PATH 环境变量')
        service = Service(chrome_driver_path)
        # 设置 Chrome 选项为无头模式
        chrome_options = Options()
        if config.get_browser_config()['headless']:
            chrome_options.add_argument('--headless')
        chrome_options.add_argument('--disable-gpu')
        chrome_options.add_argument('--start-maximized')
        chrome_options.add_argument('--no-sandbox')
        # 添加代理设置，使用本地 socks5 代理
        chrome_options.add_argument('--proxy-server=socks5://127.0.0.1:10808')
        # 隐藏 window.navigator.webdriver 特征，避免被网站检测为自动化脚本
        chrome_options.add_argument('--disable-blink-features=AutomationControlled')
        chrome_options.add_experimental_option("excludeSwitches", ["enable-automation"])
        chrome_options.add_experimental_option('useAutomationExtension', False)
        # 屏蔽无用请求，将 Google 相关域名解析到本地，避免请求这些域名
        chrome_options.add_argument('--host-resolver-rules=MAP update.googleapis.com 127.0.0.1')
        chrome_options.add_argument('--host-resolver-rules=MAP optimizationguide-pa.googleapis.com 127.0.0.1')
        chrome_options.add_argument('--host-resolver-rules=MAP accounts.google.com 127.0.0.1')
        # 优化页面加载策略，使用 'eager' 模式，即 DOM 加载完成后立即返回，不等待资源加载
        chrome_options.page_load_strategy = 'eager'
        # 随机选择一个 header 组合，增加请求的随机性
        random_header = random.choice(headers_list)
        driver = webdriver.Chrome(
            service=service,
            options=chrome_options
        )
        driver.header_overrides = random_header
        # 定义请求拦截函数，跳过包含 google 的请求
        def request_interceptor(request):
            """
            请求拦截函数，当请求的主机包含 'google' 或 'googleapis.com' 时，终止该请求。

            :param request: 拦截到的请求对象
            """
            if "google" in request.host or "googleapis.com" in request.host:
                logger.debug(f"跳过请求: {request.url}")
                request.abort()  # 直接终止请求
        driver.request_interceptor = request_interceptor
        return driver

    def close_all_drivers(self):
        while not self._driver_queue.empty():
            driver = self._driver_queue.get()
            try:
                driver.quit()
            except Exception as e:
                logger.error(f"关闭浏览器驱动时出错: {e}")



def switch_to_us(func):
    def wrapper(self, url: str, driver):
        location_text = WebDriverWait(driver, 10).until(EC.presence_of_element_located((By.CSS_SELECTOR, '#glow-ingress-line2')))
        if location_text.text == 'Fontana 92337‌':
            return func(self, url, driver)
        logger.info('正在切换到美国')
        WebDriverWait(driver, 10).until(EC.element_to_be_clickable((By.ID, 'glow-ingress-block'))).click()
        input_box = WebDriverWait(driver, 10).until(EC.presence_of_element_located((By.ID, 'GLUXZipUpdateInput')))
        input_box.send_keys(config.DEFAULT_ZIP_CODE)
        apply_btn = WebDriverWait(driver, 10).until(EC.element_to_be_clickable((By.CSS_SELECTOR, '#GLUXZipUpdate > span > input')))
        apply_btn.click()
        logger.info('apply按钮点击成功')
        time.sleep(1)
        driver.refresh()
        location_text = WebDriverWait(driver, 10).until(EC.presence_of_element_located((By.CSS_SELECTOR, '#glow-ingress-line2')))
        if location_text.text == 'Fontana 92337‌':
            logger.info('切换到美国成功')
        return func(self, url, driver)
    return wrapper


def send_request(func):
    def wrapper(self, url: str, driver):
        logger.info(f"正在访问: {url}")
        # 添加页面加载超时设置（单位：秒）
        driver.set_page_load_timeout(config.LOAD_PAGE_TIMEOUT)
        driver.get(url)
            
        # 原有状态码检测逻辑保持不变
        status_code = driver.execute_script('return performance.getEntriesByType("navigation")[0].responseStatus')
        if status_code == 429:
            logger.error(f"请求 {url} 时遇到 429 状态码")
            raise Exception(f"请求 {url} 时遇到 429 状态码")
        WebDriverWait(driver, 30).until(lambda x: x.execute_script('return document.readyState') == 'complete')
        return func(self, url, driver)
    return wrapper


class CookieManager(metaclass=SingletonMeta):

    def init(self):
        self.running = True
        self.driver = browser_factory.get_driver()
        self.cookies = {}
        self.lock = threading.Lock()
        self.update_event = threading.Event()
        self._start_cookie_updater()

    def _start_cookie_updater(self):
        """启动后台cookie更新线程"""
        self.gen_initial_cookie(config.BASE_URL, self.driver)
        def updater():
            while self.running:
                try:
                    interval = random.randint(120, 180)
                    timer = threading.Timer(interval, self.update_event.set)
                    timer.daemon = True
                    timer.start()
                    self.update_event.wait()
                    self.update_event.clear()
                    timer.cancel()
                    self._update_cookies()
                except Exception as e:
                    logger.error(f"Cookie更新线程异常: {str(e)}")

        threading.Thread(target=updater, daemon=True, name='cookie_updater').start()

    def shutdown(self):
        self.running = False
        self.update_event.set()  # 确保线程退出
        logger.info("CookieManager已关闭")

    def _update_cookies(self):
        try:
            with self.lock:
                self.driver.delete_all_cookies()
                self.driver.refresh()
                time.sleep(random.uniform(1, 3))
                self.cookies = {c['name']: c['value'] for c in self.driver.get_cookies()}
                logger.info("Cookie更新成功")
        except Exception as e:
            logger.info(f"Cookie更新异常: {str(e)}")

    def get_current_cookies(self):
        with self.lock:
            return self.cookies.copy()

    @send_request
    @switch_to_us
    def gen_initial_cookie(self, url: str):
        self.driver.get(url)
        self.cookies = {c['name']: c['value'] for c in self.driver.get_cookies()}


cookie_manager = CookieManager()
browser_factory = BrowserFactory()

